"""
@-*- coding: utf-8 -*-
@ python：python 3.8
@ 创建人员：ylx
@ 创建时间：2025/4/9 下午1:37
@ 内容：
"""

from common.log_util import *
import os.path
import sys
import pytest
from common.base_util import *
from common.yaml_hander import *
from datetime import datetime
from common.configparse import ConfigParse

# 此处作为固件或夹具，作为每次测试执行时要执行的公共方法


@pytest.fixture(autouse=True, scope="session")
def fixture_session():
    # 测试会话开始时，全局初始化调起cmd.exe，并长期保持这个会话，目的是上下文会话的一致性,测试会话结束后，关闭相应cmd.exe
    timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
    today_time = {"time": "_" + datetime.now().strftime("%Y%m%d_%H%M%S")}
    print("[info] 清除extract")
    clear_yaml()
    print("[info] 写入extract")
    write_yaml(today_time)
    print("[info] 写入extract成功")
    print(f"[info]{timestamp}:armory_client 自动化测试开始")
    sessions = CMDSession()
    yield sessions  #
    sessions.close()
    print(f"[info]{timestamp}:armory_client 自动化测试结束")


#通过autouse来配置是否开启日志记录，false为关闭
@pytest.fixture(autouse=True, scope="session")
def redirect_output():
    """重定向标准输出到控制台和日志文件"""
    # 获取当前日期和时间戳
    current_date = datetime.now().strftime("%Y-%m-%d")
    timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
    # 创建以日期命名的日志目录
    # 如果某个路径是绝对路径，则前面的会被丢弃
    log_dir = os.path.join("logs", "D:\\auto_armory", "logs", current_date)
    # 通过设置 exist_ok=True，可以避免因目录已存在而导致的异常，从而使代码更加健壮和容错
    # 如果是False 则如果目录已存在，抛出 FileExistsError 异常（默认行为）
    os.makedirs(log_dir, exist_ok=True)

    # 生成日志文件名
    log_filename = os.path.join(log_dir, f"test_log_{timestamp}.log")

    # 打开日志文件
    log_file = open(log_filename, "w", encoding="utf-8")

    # 保存原始标准输出
    original_stdout = sys.stdout

    # 重定向标准输出到控制台和日志文件
    sys.stdout = Tee(original_stdout, log_file)

    yield  # 测试运行时保持重定向

    # 测试结束后恢复原始输出并关闭日志文件
    sys.stdout = original_stdout
    log_file.close()

    # 重定向实现的原理
    # 1. 标准输出 (sys.stdout) 的工作原理
    # sys.stdout：
    # sys.stdout 是 Python 中的一个内置对象，表示标准输出流。
    # 默认情况下，sys.stdout 指向控制台（终端），因此 print() 函数会将内容输出到控制台。
    # print() 的本质：
    # print() 函数实际上是调用了 sys.stdout.write() 方法来输出内容
    # 重定向标准输出：
    # 如果我们将 sys.stdout 替换为另一个对象（如自定义类的实例）
    # 只要该对象实现了 write 方法，print() 就会调用这个新对象的 write 方法，从而实现输出重定向
    # 执行original_stdout = sys.stdout
    # sys.stdout = Tee(original_stdout, log_file)
    # 发生了以下步骤：
    # 保存原始 sys.stdout：
    # original_stdout = sys.stdout 将原始的标准输出（通常是控制台）保存到变量 original_stdout 中。
    # 替换 sys.stdout：
    # sys.stdout = Tee(original_stdout, log_file) 将 sys.stdout 替换为一个 Tee 对象。
    # 此时，sys.stdout 不再指向控制台，而是指向 Tee 对象。
    # print() 调用 Tee.write：
    # 当你调用 print() 时，它实际上会调用 sys.stdout.write()。
    # 因为 sys.stdout 现在是一个 Tee 对象，所以会调用 Tee 类中的 write 方法。
    # 在 Tee.write 方法中，输出内容会被同时写入 original_stdout（控制台）和 log_file（日志文件）
    # 使用 subprocess通过管道中的流获取输出时，需要显示的使用print来处理你需要数据，从而实现了输出的重定向
    # 注-为什么
    # 通常会通过管道（stdout = subprocess.PIPE）来捕获子进程的输出。在这种情况下，标准输出不会直接写入
    # sys.stdout，而是通过管道流传递给父进程。因此，你需要手动处理子进程的输出，并将其重定向到你希望的目标
    # 因为归根到底还是对print的修改


@pytest.fixture(autouse=False, scope="function")
def close_open_client_update(fixture_session):
    print("[info] 执行关闭客户端版本更新提示")
    start = ConfigParse().get_value("Armory_command", "配置客户端版本自动更新提示打开_1")
    fixture_session.execute(f"{start}")
    print("[info] 执行关闭客户端版本更新提示-success")
    yield
    print("[info] 执行恢复客户端版本更新提示")
    end = ConfigParse().get_value("Armory_command", "配置客户端版本自动更新提示关闭")
    fixture_session.execute(f"{end}")
    print("[info] 执行恢复客户端版本更新提示-success")

